package com.mtt.thirdapi.yanxuan.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Maps;
import com.mtt.thirdapi.yanxuan.config.YxConfig;
import com.mtt.thirdapi.yanxuan.service.HTTPService;
import com.mtt.thirdapi.yanxuan.service.YXOpenApiService;
import com.mtt.thirdapi.common.util.DateUtils;
import com.mtt.thirdapi.common.util.YXOpenApiUtils;
import com.mtt.thirdapi.common.util.YXResponseCode;
import com.mtt.thirdapi.common.api.R;
import com.mtt.thirdapi.yanxuan.vo.ApplyInfoVo;
import com.mtt.thirdapi.yanxuan.vo.OrderVO;
import com.mtt.thirdapi.yanxuan.vo.YxRefundOfferExpressVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

import static com.mtt.thirdapi.common.api.ResultCode.SUCCESS;

@Service
@Slf4j
public class YXOpenApiServiceImpl implements YXOpenApiService {

    @Autowired
    private HTTPService commonHttpService;

    @Override
    public R handleGetIds() {
        HashMap<String, String> data = Maps.newHashMap();
        return handle(YxConfig.path, data, YxConfig.getMethodIds, ".handleGetIds()");
    }

    @Override
    public R handleGetItemsById(String itemIds) {
        if (StringUtils.isEmpty(itemIds)) {
            log.error(".handleGetItemsById() fail, itemIds is null");
            return initFailureResult(YXResponseCode.FAIL, "itemIds is null");
        }
        HashMap<String, String> data = new HashMap<>();
        data.put("itemIds", itemIds);
        return handle(YxConfig.path, data, YxConfig.getMethodItems, ".handleGetItemsById()");
    }

    @Override
    public R handlePaidOrder(OrderVO order) {
        HashMap<String, String> data = new HashMap<>();
        data.put("order", JSON.toJSONString(order));
        R result = handle(YxConfig.path, data, YxConfig.paidOrderMethod, ".handlePaidOrder()");
        result.setData(JSONObject.parseObject(result.getData().toString()));
        return result;
    }


    @Override
    public R handleCancelOrder(String orderId) {
        if (StringUtils.isEmpty(orderId)) {
            log.info(".handleCancelOrder() fail, orderId is null");
            return initFailureResult(YXResponseCode.FAIL, "orderId is null");
        }
        HashMap<String, String> data = new HashMap<>();
        data.put("orderId", orderId);
        return handle(YxConfig.path, data, YxConfig.cancelOrderMethod, ".handleCancelOrder()");
    }

    @Override
    public R handleConfirmOrder(String orderId, String packageId, String confirmTime) {
        if (StringUtils.isEmpty(orderId)) {
            log.error(".handleConfirmOrder() fail,orderId is null");
            return initFailureResult(YXResponseCode.FAIL, "rderId is null");
        }
        if (StringUtils.isEmpty(packageId)) {
            packageId = "0";
        }
        if (StringUtils.isEmpty(confirmTime)) {
            confirmTime = DateUtils.parseLongToString(System.currentTimeMillis(),
                    "yyyy-MM-dd HH:mm:ss");
        }
        HashMap<String, String> data = new HashMap<>();
        data.put("orderId", orderId);
        data.put("packageId", packageId);
        data.put("confirmTime", confirmTime);
        return handle(YxConfig.path, data, YxConfig.confirmOrderMethod, ".handleConfirmOrder()");
    }

    @Override
    public R handleGetItemBySkuId(String skuId) {
        if (StringUtils.isEmpty(skuId)) {
            log.error(".handleGetItemBySkuId() fail, orderId is null");
            return initFailureResult(YXResponseCode.FAIL, "skuId is null");
        }
        HashMap<String, String> data = new HashMap<>();
        data.put("skuId", skuId);

        return handle(YxConfig.path, data, YxConfig.getItemBySkuIdMethod, ".handleGetItemBySkuId()");
    }

    @Override
    public R handleGetInventory(String skuIds) {
        if (StringUtils.isEmpty(skuIds)) {
            log.error(".handleGetInventory() fail,skuIds is null");
            return initFailureResult(YXResponseCode.FAIL, "skuIds is null");
        }
        HashMap<String, String> data = new HashMap<>();
        data.put("skuIds", JSON.toJSONString(skuIds.split(",")));
        R result = handle(YxConfig.path, data, YxConfig.getInventoryMethod, ".handleGetInventory()");

        result.setData(JSONArray.parseArray(result.getData().toString()));
        return result;
    }

    @Override
    public R handleGetOrder(String orderId) {
        if (StringUtils.isEmpty(orderId)) {
            log.error(".handleGetOrder() fail, orderId is null");
            return initFailureResult(YXResponseCode.FAIL, "orderId is null");
        }
        HashMap<String, String> data = new HashMap<>();
        data.put("orderId", orderId);
        R result = handle(YxConfig.path, data, YxConfig.getOrderMethod, ".handleGetOrder()");
        result.setData(JSONObject.parseObject(result.getData().toString()));
        return result;


    }

    @Override
    public R handleRegisterCallback(String methods) {
        if (StringUtils.isEmpty(methods)) {
            log.error(".handleRegisterCallback() fail,methods is null");
            return initFailureResult(YXResponseCode.FAIL, "methods is null");
        }
        HashMap<String, String> data = new HashMap<>();
        data.put("methods", methods.replace(" ",""));
        return handle(YxConfig.path, data, YxConfig.registerCallbackMethod, ".handleRegisterCallback()");
    }

    @Override
    public R handleRefundOrderApply(ApplyInfoVo applyInfoVo) {
        String applyInfo = JSON.toJSONString(applyInfoVo);
        HashMap<String, String> data = new HashMap<>();
        data.put("applyInfo", applyInfo);
        R result = handle(YxConfig.path, data, YxConfig.refundOrderApplyMethod, ".handleRefundOrderApply()");
        result.setData(JSONObject.parseObject(result.getData().toString()));
        return result;

    }

    @Override
    public R handleRefundOrderCancel(String applyId) {
        if (StringUtils.isEmpty(applyId)) {
            log.error(".handleRefundOrderCancel() fail,applyId is null", applyId);
        }
        HashMap<String, String> data = new HashMap<>();
        data.put("applyId", applyId);
        return handle(YxConfig.path, data, YxConfig.refundOrderCancelMethod, ".handleRefundOrderCancel()");
    }

    @Override
    public R handleMockCallbackRefundReject(String applyId) {
        if (StringUtils.isEmpty(applyId)) {
            log.error(".handleMockCallbackRefundReject() fail, applyId is null");
            return initFailureResult(YXResponseCode.FAIL, "applyId is null");
        }
        HashMap<String, String> data = new HashMap<>();
        data.put("applyId", applyId);
        return handle(YxConfig.mackApiPathPrefix + YxConfig.mockCallbackRefundReject, data,
                YxConfig.mockCallbackRefundReject, ".handleMockCallbackRefundReject()");
    }

    @Override
    public R handleRefundOrderOfferExpress(YxRefundOfferExpressVo yxRefundOfferExpressVo) {
        HashMap<String, String> data = new HashMap<>();
        data.put("applyId", yxRefundOfferExpressVo.getApplyId());
        data.put("expressInfo", JSON.toJSONString(yxRefundOfferExpressVo.getExpressInfo()));
        return handle(YxConfig.path, data, YxConfig.refundOrderOfferExpress, ".handleRefundOrderOfferExpress()");
    }

    @Override
    public R handleRefundOrderDetail(String applyId) {
        HashMap<String, String> data = new HashMap<>();
        data.put("applyId", applyId);
        R result = handle(YxConfig.path, data, YxConfig.refundOrderDetail, ".handleRefundOrderDetail()");
        result.setData(JSONObject.parseObject(result.getData().toString()));
        return result;
    }

    @Override
    public R handleMockCallbackRefundExpressConfirm(String applyId) {
        HashMap<String, String> data = new HashMap<>();
        data.put("applyId", applyId);

        return handle(YxConfig.mackApiPathPrefix + YxConfig.callbackRefundExpressConfirm, data,
                YxConfig.callbackRefundExpressConfirm, ".handleMockCallbackRefundExpressConfirm()");
    }

    @Override
    public R handleMockCallbackRefundSystemCancel(String applyId) {
        HashMap<String, String> data = new HashMap<>();
        data.put("applyId", applyId);
        return handle(YxConfig.mackApiPathPrefix + YxConfig.callbackRefundSystemCancel, data,
                YxConfig.callbackRefundSystemCancel, ".handleMockCallbackRefundSystemCancel()");
    }

    @Override
    public R handleCallbackRefundResultDirectly(String applyId) {
        HashMap<String, String> data = new HashMap<>();
        data.put("applyId", applyId);
        return handle(YxConfig.mackApiPathPrefix + YxConfig.callbackRefundResultDirectly, data,
                YxConfig.callbackRefundResultDirectly, ".handleCallbackRefundResultDirectly()");
    }

    @Override
    public R handleMockCallbackRefundResultWithExpress(String applyId, boolean allApproved) {
        HashMap<String, String> data = new HashMap<>();
        data.put("applyId", applyId);
       // data.put("allApprove", String.valueOf(allApproved));
        return handle(YxConfig.mackApiPathPrefix + YxConfig.callbackRefundResultWithExpress, data,
                YxConfig.callbackRefundResultWithExpress, ".handleMockCallbackRefundResultWithExpress()");
    }

    @Override
    public R handleItemSkuDiscount(String skuIds) {
        HashMap<String, String> data = new HashMap<>();
        data.put("skuIds",skuIds);
        //data.put("skuIds", JSON.toJSONString(skuIds.split(",")));
        R result = handle(YxConfig.path, data, YxConfig.itemSkuDiscount, ".handleItemSkuDiscount()");
        return result;
    }

    @Override
    public R handleGetCallBackMeheods() {
        HashMap<String, String> data = new HashMap<>();
        R result = handle(YxConfig.path, data, YxConfig.getCallBackMethod, ".handleGetCallBackMeheods()");
        result.setData(JSONObject.parseArray(result.getData().toString()));
        return result;
    }

    @Override
    public R handleMockCallbackOrderCancel(String orderId) {
        if (StringUtils.isEmpty(orderId)) {
            log.error(".handleMockCallbackOrderCancel() fail,orderId is null");
            return initFailureResult(YXResponseCode.FAIL, "orderId is null");
        }
        HashMap<String, String> data = new HashMap<>();
        data.put("orderId", orderId);
        return handle(YxConfig.mackApiPathPrefix + YxConfig.mockCallbackCancelOrder, data,
                YxConfig.mockCallbackCancelOrder, ".handleMockCallbackOrderCancel()");
    }

    @Override
    public R handleMockCallbackAuditCancelOrder(String orderId, boolean cancel) {
        if (StringUtils.isEmpty(orderId)) {
            log.error(".handleMockCallbackAuditCancelOrder() fail, orderId is null");
            return initFailureResult(YXResponseCode.FAIL, "orderId is null");
        }
        HashMap<String, String> data = new HashMap<>();
        data.put("orderId", orderId);
        data.put("cancel", String.valueOf(cancel));
        return handle(YxConfig.mackApiPathPrefix + YxConfig.mockCallbackAuditCancelOrder, data,
                YxConfig.mockCallbackAuditCancelOrder, ".handleMockCallbackAuditCancelOrder()");

    }

    @Override
    public R handleMockCallbackDeliveryOrder(String orderId) {
        if (StringUtils.isEmpty(orderId)) {
            log.error(".handleMockCallbackDeliveryOrder() fail, orderId is null");
            return initFailureResult(YXResponseCode.FAIL, "orderId is null");
        }
        HashMap<String, String> data = new HashMap<>();
        data.put("orderId", orderId);
        return handle(YxConfig.mackApiPathPrefix + YxConfig.mockCallbackDeliveryOrder, data,
                YxConfig.mockCallbackDeliveryOrder, ".handleMockCallbackDeliveryOrder()");
    }

    @Override
    public R handleMockCallbackRefundAddress(String applyId, int type) {
        if (StringUtils.isEmpty(applyId)) {
            log.error(".handleMockCallbackRefundAddress() fail,applyId is null");
            return initFailureResult(YXResponseCode.FAIL, "applyId is null");
        }
        HashMap<String, String> data = new HashMap<>();
        data.put("applyId", applyId);
        data.put("type", String.valueOf(type));
        return handle(YxConfig.mackApiPathPrefix + YxConfig.mockCallbackRefundAddress, data,
                YxConfig.mockCallbackRefundAddress, ".handleMockCallbackRefundAddress()");
    }


    private R handle(String path, HashMap<String, String> data, String method, String logTag) {
        // 构建时间戳
        long currentTime = System.currentTimeMillis();
        String timestamp = DateUtils.parseLongToString(currentTime,
                "yyyy-MM-dd HH:mm:ss");
        TreeMap<String, String> paramsMap = YXOpenApiUtils.packageParams(YxConfig.appKey, YxConfig.appSecret, timestamp, method, data);
        // 组装参数
        List<NameValuePair> params = new ArrayList<>();
        for (Map.Entry<String, String> entry : paramsMap.entrySet()) {
            params.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
        }
        String url = YxConfig.yxOpenApiHost + path;

        try {
            long t1 = System.currentTimeMillis();

            // 调用严选open api
            String response = commonHttpService.doPost(url, params, "utf-8");

            long t2 = System.currentTimeMillis();

            log.info("{} method={}, params={}, response={}, 耗时={}",
                    logTag, method, JSON.toJSONString(params), response, t2 - t1);

            return handleResponse(response);
        } catch (Exception e) {
            log.error("{} Exception={}, method={}, params={}",
                    logTag, e.getMessage(), method, JSON.toJSONString(params));
            return initServerError();
        }
    }

    private R handleResponse(String response) {

        if (StringUtils.isEmpty(response)) {
            if (null != log) {
                log.error(".handleResponse() response is empty");
            }
            return initServerError();
        }

        JSONObject responseObj = JSON.parseObject(response);

        String code = responseObj.getString("code");

        if (code.equals("200")) {
            return initSuccessResult(responseObj.get("result"));
        } else {
            if (null != log) {
                log.error(".handleResponse() fail. response={}", response);
            }
            return initServerError();
        }
    }

    private R initServerError() {
        return initFailureResult(YXResponseCode.SERVER_ERROR, "server error");
    }

    private R initFailureResult(int code, String msg) {
        return R.fail(code, msg);
    }

    private R initSuccessResult(Object result) {
        R success = R.success(SUCCESS);
        success.setData(result);
        return success;
    }
}
